---
title: Prompting Best Practices
description: "Write effective prompts for reliable Stagehand automation"
---
import { V3Banner } from '/snippets/v3-banner.mdx';

<V3Banner />


Good prompts make Stagehand reliable. Bad prompts cause failures. Here's how to write prompts that work consistently.

## Act Method

Use `act()` for single actions on web pages. Each action should be focused and clear.

```typescript
// Good - Single, specific actions
await stagehand.act("click the 'Add to Cart' button");
await stagehand.act("type 'user@example.com' into the email field");

// Bad - Multiple actions combined
await stagehand.act("fill out the form and submit it");
await stagehand.act("login with credentials and navigate to dashboard");
```

### Use Element Types, Not Colors

Describe elements by their type and function rather than visual attributes like color.

```typescript
// Good - Element types and descriptive text
await stagehand.act("click the 'Sign In' button");
await stagehand.act("type into the email input field");

// Bad - Color-based descriptions
await stagehand.act("click the blue button");
await stagehand.act("type into the white input");
```

### Use Descriptive Language

```typescript
// Good - Clear element identification
await stagehand.act("click the 'Next' button at the bottom of the form");
await stagehand.act("type into the search bar at the top of the page");

// Bad - Vague descriptions
await stagehand.act("click next");
await stagehand.act("type into search");
```

### Choose the Right Action Verbs

- **Click** for buttons, links, checkboxes
- **Type** for text inputs
- **Select** for dropdowns
- **Check/uncheck** for checkboxes
- **Upload** for file inputs

```typescript
// Good
await stagehand.act("click the submit button");
await stagehand.act("select 'Option 1' from dropdown");

// Bad
await stagehand.act("click submit");
await stagehand.act("choose option 1");
```

### Protect Sensitive Data

Variables keep sensitive information out of prompts and logs.

```typescript
// Use variables for sensitive data
await stagehand.act("type %username% into the email field", {
  variables: { username: "user@example.com" }
});

await stagehand.act("type %password% into the password field", {
  variables: { password: process.env.USER_PASSWORD }
});
```

<Warning>
Set `verbose: 0` in your Stagehand config to prevent secrets from appearing in logs.
</Warning>

## Extract Method

Use `extract()` to pull structured data from pages. Define clear schemas and provide context.

### Schema Best Practices

Use descriptive field names, correct types, and detailed descriptions. Field descriptions provide context that helps the model understand exactly what to extract.

```typescript
// Good - Descriptive names, correct types, and helpful descriptions
const productData = await stagehand.extract(
  "Extract product information",
  z.object({
    productTitle: z.string().describe("The main product name displayed on the page"),
    priceInDollars: z.number().describe("Current selling price as a number, without currency symbol"),
    isInStock: z.boolean().describe("Whether the product is available for purchase")
  })
);

// Bad - Generic names, wrong types, no descriptions
const data = await stagehand.extract(
  "Get product details",
  z.object({
    name: z.string(), // Too generic, no context
    price: z.string(), // Should be number
    stock: z.string() // Should be boolean, no context
  })
);
```

### Use Proper URL Types

Specify URL types with `z.string().url()` to tell Stagehand to extract URLs.

```typescript
// Good - Tells Stagehand to extract URLs
const links = await stagehand.extract(
  "Extract navigation links",
  z.array(z.object({
    text: z.string(),
    url: z.string().url() // Required for URL extraction
  }))
);

// Single URL extraction
const contactUrl = await stagehand.extract(
  "extract the contact page URL",
  z.string().url()
);
```

## Observe Method

Use `observe()` to discover actionable elements before acting on them.

### Check Elements First

Verify elements exist before taking action to avoid errors.

```typescript
// Check for elements first
const loginButtons = await stagehand.observe("Find the login button");

if (loginButtons.length > 0) {
  await stagehand.act(loginButtons[0]);
} else {
  console.log("No login button found");
}
```

### Be Specific About Element Types

```typescript
// Good - Specific element types
const submitButtons = await stagehand.observe("Find submit button in the form");
const dropdowns = await stagehand.observe("Find the state dropdown menu");

// Bad - Too vague
const elements = await stagehand.observe("Find submit stuff");
const things = await stagehand.observe("Find state selection");
```

## Agent Method

Use `agent()` for complex, multi-step workflows. Provide detailed instructions and set appropriate limits.

### Navigate First

Don't include navigation in agent tasks. Handle it separately.

```typescript
// Good - Navigate first
await page.goto('https://amazon.com');
await agent.execute('Search for wireless headphones under $100 and add the best rated one to cart');

// Bad - Navigation in task
await agent.execute('Go to Amazon, search for headphones, and add one to cart');
```

### Be Highly Specific

Detailed instructions lead to better results.

```typescript
// Good - Detailed instructions
await agent.execute({
  instruction: "Find Italian restaurants in Brooklyn that are open after 10pm, have outdoor seating, and are rated 4+ stars. Save the top 3 results.",
  maxSteps: 25
});

// Bad - Vague instructions
await agent.execute("Find some good restaurants");
```

### Set Appropriate Step Limits

Match step limits to task complexity.

```typescript
// Simple task - fewer steps
await agent.execute({
  instruction: "Subscribe to the newsletter with email 'user@example.com'",
  maxSteps: 10
});

// Complex task - more steps  
await agent.execute({
  instruction: "Research and compare 5 project management tools with pricing and features",
  maxSteps: 50
});
```

### Include Success Criteria

Tell the agent how to know when it's done.

```typescript
// Good - Clear success criteria
await agent.execute({
  instruction: "Add 3 smartphone cases to cart and confirm the cart shows exactly 3 items with total price",
  maxSteps: 20
});

// Bad - No validation
await agent.execute("Add some items to cart");
```

## Common Mistakes to Avoid

- **Combining multiple actions** - Keep each `act()` call to one action
- **Using vague descriptions** - Be specific about which elements to interact with  
- **Exposing sensitive data** - Always use variables for credentials
- **Skipping validation** - Check results before proceeding

## Testing Your Prompts

1. **Start simple** - Test basic functionality first
2. **Add complexity gradually** - Build up to complex workflows
3. **Monitor results** - Use logging to understand what's happening
4. **Iterate based on failures** - Refine prompts when they don't work
Remember: Good prompting is iterative. When in doubt, be more specific rather than less.